import { OlDraw, OlVectorLayer } from './type'
import { createBox, createRegularPolygon } from 'ol/interaction/Draw'
import VectorSource from 'ol/source/Vector'
import LngLat from './WLngLat'
import { toLonLat } from 'ol/proj'
import { commonStyle, formatRadiusToMeters } from './utils'

/**
 * 矢量图形类
 * @param {*} map 地图实例
 * @param {*} type 矢量图形类型 （点 Point/线 Line/圆 Circle/多边形 Polygon/长方形 Rectangle/正方形 Square）
 * @param {*} status 绘制 paint / 编辑 edit
 * @param {*} options 配置参数
 * options = {
 *    center: '',
 *    radius: 100,
 *    strokeColor: ''
 *    ...
 * }
 */
class WGraph {
	constructor(map, options = {}) {
		this.map = map
		this.WTYPE = 'GRAPH'
		this.olTarget = null // 被动绘制对象
		this.drawTarget = null // 主动绘制对象
		this.source = null // 数据源
		this.vector = null // 准备放在图层上的数据元素
		this.drawFeature = null
		this.events = ['done'] // 支持的事件
		this.clickTimeId = null //单击事件定时器
		this.WEvents = new Map() // 存储事件
		this.graphTool = {
			// 绘制工具列表
			Point: {
				status: false,
				style: null
			},
			Line: {
				status: false,
				style: null
			},
			Circle: {
				status: false,
				style: null
			},
			Rectangle: {
				status: false,
				style: null
			},
			Polygon: {
				status: false,
				style: null
			},
			Square: {
				status: false,
				style: null
			}
		}
		/**
		 * 开始绘制
		 */
		this.beginPaint = function (type) {
			console.log(type)
			let geometryFunction // 更新几何坐标时调用的函数。
			let penValue = 'Circle' // 笔尖类型 默认为Circle
			switch (type) {
				// 点和线 目前暂未开发
				case 'Point':
					penValue = 'Point'
					break
				case 'Line':
					penValue = 'LineString'
					break
				// 默认不写参数 即为圆形
				case 'Circle':
					break
				case 'Polygon':
					penValue = 'Polygon'
					break
				case 'Rectangle':
					geometryFunction = this.paintRectangle()
					break
				case 'Square':
					geometryFunction = this.paintSquare()
					break
			}
			if (this.graphTool[type].style) {
				this.vector.setStyle(this.graphTool[type].style)
			}
			let freehandFlag = false
			switch (type) {
				case 'Polygon':
				case 'Line':
					freehandFlag = false
					break
				default:
					freehandFlag = true
					break
			}
			this.drawTarget = new OlDraw({
				// 数据源
				source: this.source,
				// 绘制类型
				type: penValue,
				geometryFunction: geometryFunction,
				freehand: freehandFlag, // 手绘模式
				stopClick: true
			})
			// 将draw对象添加到map中，然后就可以进行图形绘制了
			this.map.addGraph(this.drawTarget)
			this.drawTarget.setActive(true)
			this.drawTarget.addEventListener('drawstart', () => {})
			this.drawTarget.addEventListener('drawend', e => {
				this.deactivate()
				// 将当前绘制的矢量图形 通过done事件触发抛出去
				let targets = this.WEvents.get('WGraph(done)')
				if (targets) {
					this.drawFeature = this.buildFeature(e)
					e.feature.set('WTYPE', 'OlDraw')
					window.dispatchEvent(targets.costomEvent)
				}
			})
		}
		this.initGraph(options) // 初始化矢量图层样式
	}
	/**
	 * 对数据进行修改筛选，不将原生数据返回给用户
	 */
	buildFeature(e) {
		let feature = e.feature
		const geo = feature.getGeometry()
		let data = {}
		const type = this.judgeShape(geo)
		if (type === 'Point') {
			e.lnglat = new LngLat(...toLonLat(geo.getCoordinates()))
			data = e.lnglat
		} else if (type === 'Line') {
			const points = geo.getCoordinates()
			e.lnglat = []
			for (let i = 0; i < points.length; i++) {
				e.lnglat.push(new LngLat(...toLonLat(points[i])))
			}
			data = e.lnglat
		} else if (type === 'Circle') {
			e.lnglat = new LngLat(...toLonLat(geo.getCenter()))
			data = {
				center: e.lnglat,
				radius: Number(formatRadiusToMeters(geo).toFixed(1))
			}
		} else if (type === 'Polygon') {
			const points = geo.getCoordinates().flat(1)
			e.lnglat = []
			// 左上开始 逆时针
			for (let i = 0; i < points.length; i++) {
				e.lnglat.push(new LngLat(...toLonLat(points[i])))
			}
			data = e.lnglat.slice(1)
		} else if (type === 'Rectangle') {
			const points = geo.getCoordinates().flat(1)
			e.lnglat = []
			// 左下开始 逆时针
			for (let i = 0; i < points.length; i++) {
				e.lnglat.push(new LngLat(...toLonLat(points[i])))
			}
			data = [e.lnglat[0], e.lnglat[2]]
		}
    e.target.feature = feature
		return {
			target: e.target,
			type: type,
			data: data
		}
	}
	/**
	 * 激活矢量图绘制deactivate
	 * @param {*} graphName
	 */
	activate(graphName) {
		if (this.graphTool[graphName]) {
			this.beginPaint(graphName) // 开始绘图
		} else {
			console.warn(`WMapJs VectorGraph类无${graphName}`)
		}
	}
	/**
	 * 失活矢量图绘制
	 */
	deactivate() {
		if (this.drawTarget) {
			this.drawTarget.setActive(false)
			this.drawTarget = null
		}
		this.stopPaint()
	}
	/**
	 * 获取 自定义数据
	 */
	getExtData() {
		if (!this.olTarget) {
			console.warn('矢量图形未初始化喔~')
		} else {
			return this.olTarget.get('extData')
		}
	}
	/**
	 * 判断矢量图形形状
	 * e 等同于 feature.getGeometry()
	 */
	judgeShape(e) {
		let type = e.getType()
		if (type === 'Polygon') {
			let arr = e.getCoordinates().flat()
			if (arr.length === 5) {
				const rect = arr.slice(0, 4)
				if ((rect[0][0] === rect[1][0] && rect[0][1] === rect[3][1]) || (rect[0][1] === rect[1][1] && rect[0][0] === rect[3][0])) {
					type = 'Rectangle'
				}
			}
		} else if (type === 'LineString') {
			type = 'Line'
		}
		return type
	}
	/**
	 * 初始化矢量图形
	 */
	initGraph(options) {
		// 取到map类已实例化的矢量图层
		if (this.map.getVectorLayer()) {
			this.vector = this.map.getVectorLayer()
			this.source = this.vector.getSource()
			const style = commonStyle(options)
			this.vector.setStyle(style)
		} else {
			this.source = new VectorSource({ wrapX: false })
			this.vector = new OlVectorLayer({
				className: 'WMap-vector-layer',
				// 数据源
				source: this.source,
				// 样式
				style: () => {
					const styles = commonStyle(options)
					return styles
				}
			})
			this.map.addLayer(this.vector) // 添加到图层上
		}
	}
	/**
	 * 清除图层上的数据源（矢量图形）
	 * @param {*} e
	 */
	clearVector() {
		if (!this.source) {
			console.warn('VectorSource Class warn: source is null!')
			return
		}
		this.source.clear()
	}
	/**
	 * 停止绘制
	 */
	stopPaint() {
		if (this.drawTarget) {
			this.map.removeGraph(this.drawTarget)
		}
	}
	/**
	 * 绘制矩形
	 */
	paintRectangle() {
		return createBox()
	}
	/**
	 * 绘制正方形
	 * @param {*} params
	 */
	paintSquare() {
		return createRegularPolygon(4)
	}
	// 事件注册
	on(eventName, callBack = () => {}) {
		if (!eventName || typeof eventName !== 'string') throw new Error('请传入正确的 eventName！')
		if (!this.events.includes(eventName)) return console.warn('无效的事件：' + eventName)
		const eventObject = {
			eventName: 'WGraph(' + eventName + ')',
			callBack,
			handler: e => {
				e.callBack({
					type: e.eventName,
					target: e.target,
					event: e.event
				})
			}
		}
		// 未绑定过事件
		if (!this.WEvents.has(eventObject.eventName)) {
			let eve = document.createEvent('HTMLEvents')
			eve.initEvent(eventName, false, true)
			eve.callBack = callBack
			eventObject.costomEvent = eve
			window.addEventListener(eventName, e => e.callBack && e.callBack(this.drawFeature))
			//储存事件
			this.WEvents.set(eventObject.eventName, eventObject)
		} else {
			const currentEventObject = this.WEvents.get(eventObject.eventName)
			//储存新事件
			this.WEvents.set(currentEventObject.eventName, eventObject)
		}
		this.olTarget && this.olTarget.set('WEvents', this.WEvents)
	}
	//事件移除
	off(eventName, callBack = () => {}) {
		eventName = 'WGraph(' + eventName + ')'
		if (this.WEvents.has(eventName)) {
			// 获取事件对象
			const currentEventObject = this.WEvents.get(eventName)
			// 移除事件
			this.olTarget.un(currentEventObject.eventName, currentEventObject.handler)
			// 删除事件存储
			this.WEvents.delete(eventName)
			this.olTarget && this.olTarget.set('WEvents', this.WEvents)
			callBack()
		}
	}
}

export default WGraph
